#region imported Namespace
using System;
using System.Data;
using System.Data.SqlClient;

using Utility = PHSRAG.Utility;
using SalaryDistribConstants = PHSRAG.Insight21.Personnel.Constants.SalaryDistributionsConstants;
using PerDetailConstants = PHSRAG.Insight21.Personnel.Constants.PersonnelDetailsConstants;
using SalaryAdjustmentConstants = PHSRAG.Insight21.Personnel.Constants.SalaryAdjustmentsConstants;
#endregion

namespace PHSRAG.Insight21.Personnel
{
	#region Validations helper class
	/// <summary>
	/// The Validation helper provides methods for business validations to be carried out
	/// before add/edit salary or salry distributions.It is the responsibility of the 
	/// caller to catch the exception that is propagated/thrown by methods within this class.
	/// </summary>
	public class ValidationsHelper
	{
		#region Constants
		//Stored Procedure Name
		private static string ValidateFundSPROCName				= "ValidateFundNumber";
		#endregion

		#region Static methods
		/// <summary>
		/// Validate if the effective date is within the hire date of the employee
		/// Validation is used both for salary and salary distribution add and update
		/// </summary>
		/// <param name="dataContainer">Dataset with the data for validation</param>
		/// <param name="effectiveDate">Effective data entered by the user</param>
		public static void ValidateEffectiveDate
			(DataSet dataContainer,DateTime effectiveDate)
		{
			object hireDate = dataContainer.Tables[PerDetailConstants.PersonnelDetailsTableName].
				Rows[0][PerDetailConstants.HireDateColumnName];

			string hireDateValue = (hireDate == DBNull.Value)
				?string.Empty:(Convert.ToDateTime(hireDate)).ToString("MM/dd/yyyy");			
			
			if(hireDateValue != string.Empty)
				if(effectiveDate < Convert.ToDateTime(hireDateValue))
					throw new Exception(@"Effective date cannot be before hiredate");
		}
		/// <summary>
		/// Validate if the date range for the added distribution overlaps
		/// any existing distribution date range for the same fund number
		/// </summary>
		/// <param name="distribTable">DataTable containing salary distribution data</param>
		/// <param name="effectiveDate">Distribution effective date entered by the user</param>
		/// <param name="fundNumber">Fund number entered by the user</param>
		public static void ValidateDistributionOverlapforAdd
			(DataTable distribTable,DateTime effectiveDate,string fundNumber)
		{
			foreach(DataRow distribRow in distribTable.Rows)
			{
				//If the fund is same and if it is not the newly added row
				if (fundNumber.Equals(distribRow[SalaryDistribConstants.FundNumberColumnName].ToString()) && 
					distribRow[SalaryDistribConstants.DistributionIDColumnName] != DBNull.Value)
				{
					//Check for the date overlap
					if (effectiveDate >= 
						Convert.ToDateTime(distribRow[SalaryDistribConstants.EffectiveDateColumnName]) && 
						effectiveDate <= 
						Convert.ToDateTime(distribRow[SalaryDistribConstants.ExpirationDateColumnName].ToString()))
					{
						throw new Exception
							(@"The distribution you are adding overlaps with an existing distribution");
					}
				}
			}			
		}
		/// <summary>
		/// Validate if the date range for the edited distribution overlaps
		/// any existing distribution date range for the same fund number
		/// </summary>
		/// <param name="distribTable">DataTable containing salary distribution data</param>
		/// <param name="effectiveDate">Distribution effective date entered by the user</param>
		/// <param name="distributionID">Id of the distribution being edited</param>
		/// <param name="fundNumber">Fund number entered by the user</param>
		public static void ValidateDistributionOverlapforUpdate
			(DataTable distribTable,DateTime effectiveDate,int distributionID,string fundNumber)
		{
			foreach(DataRow distribRow in distribTable.Rows)
			{
				//Skip the row with the same DistributionId...
				if(Convert.ToInt32(distribRow[SalaryDistribConstants.DistributionIDColumnName]) != distributionID)
				{
					if (fundNumber.Equals(distribRow[SalaryDistribConstants.FundNumberColumnName].ToString()))
					{
						if (effectiveDate >= 
							Convert.ToDateTime(distribRow[SalaryDistribConstants.EffectiveDateColumnName]) && 
							effectiveDate <= 
							Convert.ToDateTime(distribRow[SalaryDistribConstants.ExpirationDateColumnName].ToString()))
						{
							throw new Exception
								(@"The distribution you are editing overlaps with an existing distribution");
						}
					}
				}
			}			
		}
		/// <summary>
		/// Validate if the effective date of the salary adjustment being updated
		/// is the same as the effective date of any existing salary adjustment
		/// </summary>
		/// <param name="salaryTable">DataTable containing salary adjustment data</param>
		/// <param name="effectiveDate">Salary effective date</param>
		/// <param name="salaryID">ID of the edited salary row</param>
		public static void ValidateEffectiveDateforSalaryUpdate
			(DataTable salaryTable,DateTime effectiveDate,int salaryID)
		{
			foreach(DataRow salaryRow in salaryTable.Rows)
			{
				if(Convert.ToInt32(salaryRow[SalaryAdjustmentConstants.SalaryIDColumnName]) != salaryID)
				{
					if(effectiveDate ==
						Convert.ToDateTime(salaryRow[SalaryAdjustmentConstants.EffectiveDateColumnName]))
						throw new Exception(@"A salary adjustment with the effective date already exists.");
				}
			}
		}
		/// <summary>
		/// Validate if the effective date of the salary adjustment being added
		/// is the same as the effective date of any existing salary adjustment
		/// </summary>
		/// <param name="salaryTable">DataTable containing salary adjustment data</param>
		/// <param name="effectiveDate">Salary effective date</param>
		public static void ValidateEffectiveDateforSalaryAdd
			(DataTable salaryTable,DateTime effectiveDate)
		{
			foreach(DataRow salaryRow in salaryTable.Rows)
			{
				if(salaryRow[SalaryAdjustmentConstants.SalaryIDColumnName] != DBNull.Value)
				{
					if(effectiveDate ==
						Convert.ToDateTime(salaryRow[SalaryAdjustmentConstants.EffectiveDateColumnName]))
						throw new Exception(@"A salary adjustment with the effective date already exists.");
				}
			}
		}
		/// <summary>
		/// Validate the entered fund number
		/// Check whether the fund number valid, if valid check whether the user has access on the fund
		/// </summary>
		/// <param name="connectionString">Data base connection string</param>
		/// <param name="fundNumber">Fund number entered by the user</param>
		public static void ValidateFundNumber
			(string connectionString,string fundNumber)
		{
			int resultValue = (int)Utility.DataAccess.ExecuteScalar(connectionString,ValidateFundSPROCName
				,Utility.DataAccess.BuildSqlParameterArray
				("@fundNumber",SqlDbType.VarChar,fundNumber));
			
			if(resultValue == 1)
				throw new Exception(string.Format(@"Fund Number '{0}' is invalid.Please re-enter", fundNumber));
		}
		#endregion
	}
	#endregion
}